package com.netscenery.yang.writer;

import com.netscenery.yang.YangStatement;


public class YangWriter {
//	private String curIndentation;
//	/**
//	 * ���¶��������
//	 */
//	public static final int YANGWRITER_OK = 0;
//	public static final int YANGWRITER_FAIL = -1;
//	
//	
//	/**
//	 * ��ʼYANGת�������formatû����գ��򷵻�ʧ��
//	 * @return
//	 */
//	public int start(){
//		if (null != curIndentation){
//			return YANGWRITER_FAIL;
//		}
//		return YANGWRITER_OK;
//	}
//	public void end(){
//		if(null != curIndentation){
//			curIndentation = null;
//		}
//	}
	private static String convert2DQValue(String value){
		if (null == value){
			return null;
		}
		StringBuffer sb = new StringBuffer();
		sb.append("\"");
		int length = value.length();
		for (int i = 0; i < length;i++){
			char c = value.charAt(i);
			//ת���ַ���
//			if ('\\' == c){
//				sb.append("\\\\");
//				
//			}
//			else 
			if ('"' == c){
				sb.append("\\\"");
			}
			else if ('\n' == c){
				sb.append("\\n");
			}
			else{
				sb.append(c);
			}
		}
		sb.append("\"");	
		return sb.toString();
	}
	private static String convert2QuotesValue(String value){
		boolean useSingleQuote = false;
		if (null == value){
			return null;
		}
		StringBuffer sb = new StringBuffer();
		if (value.contains("'")){
			useSingleQuote = false;
		}
		else {
			useSingleQuote = true;
		}
		if (false == useSingleQuote){
			sb.append("\"");
			int length = value.length();
			for (int i = 0; i < length;i++){
				char c = value.charAt(i);
				//ת���ַ���
//				if ('\\' == c){
//					sb.append("\\\\");
//					
//				}
//				else 
				if ('"' == c){
					sb.append("\\\"");
				}
				else{
					sb.append(c);
				}
			}
			sb.append("\"");
		}
		else {
			sb.append("'");
			sb.append(value);
			sb.append("'");
		}

		
		return sb.toString();
	}
//	private String toYangSingleLine(YangStatement statement, YangFormatter format){
//		String yangStr;
//		String curIndentation = this.curIndentation;
//		
//		if (null == this.curIndentation){
//			this.curIndentation = format.getIndentation();
//		}
//		else{
//			this.curIndentation += format.getIndentation();
//		}
//		
//		yangStr = this.curIndentation;
//		yangStr += statement.getKeyword();
//		yangStr += " ";
//		if (statement.isIsNeedQuotes()){
//			yangStr += "\"";
//		}
//		yangStr += statement.getArgument();
//		if (statement.isIsNeedQuotes()){
//			yangStr += "\"";
//		}
//		yangStr += ";";
//		yangStr += format.getEndWith();
//		this.curIndentation = curIndentation;
//		return yangStr;
//	}
//	
//	private String toYangContainer(YangStatement statement, YangFormatter format){
//		String yangStr ;
//		String curIndentation = this.curIndentation;
//		int index = 0;
//		int childrenNumber = statement.getChildrenNumber();
//		YangStatement childElement;
//		
//		if (null == this.curIndentation){
//			this.curIndentation = format.getIndentation();
//		}
//		else{
//			this.curIndentation += format.getIndentation();
//		}
//		yangStr = this.curIndentation;
//		yangStr += statement.getKeyword();
//		yangStr += " ";
//		if (statement.isIsNeedQuotes()){
//			yangStr += "\"";
//		}
//		yangStr += statement.getArgument();
//		if (statement.isIsNeedQuotes()){
//			yangStr += "\"";
//		}
//		yangStr += " {";
//		yangStr += format.getEndWith();
//		for (index = 0; index< childrenNumber;index++){
//			childElement = statement.getChild(index);
//			if (null == childElement){
//				continue;
//			}
//			yangStr += toYANG(childElement,format);
//		}
//		yangStr += this.curIndentation;
//		yangStr += "}";
//		yangStr += format.getEndWith();
//		this.curIndentation = curIndentation;
//		return yangStr;
//	}
//	
//	public String toYANG(YangStatement statement, YangFormatter format){
//		String yangStr;
//		if (null == statement){
//			return null;
//		}
//		
//		if(statement.hasChildren()){
//			yangStr = toYangContainer(statement,format);
//		}
//		else{
//			yangStr = toYangSingleLine(statement,format);
//		}
//		
//		return yangStr;
//	}
	private static String buildLinePrefix(int size){
		StringBuffer sBuffer = new StringBuffer();
		sBuffer.append("\n");
		for (int i = 0; i < size; i++){
			sBuffer.append(" ");
		}
		
		return sBuffer.toString();
	}
	/**
	 * 
	 * @param beginPos
	 * @param string
	 * @param columnSize
	 * @return
	 */
	private static String adjustString(int beginPos,String inStr,int columnSize){
		StringBuffer sb= new StringBuffer();
		if (null == inStr){
			return null;
		}
		//����п�С�ڲ������ʼ��ַ�����п����Ϊ��ʼλ�ü�40
		if (columnSize <= beginPos){
			columnSize = beginPos + 40;
		}
		//�����ʼλ�ó���40�����п��Զ�����40
		if (beginPos >= 40){
			columnSize += 40;
		}
		//��������ַ�ĳ���С���п��ȥ��ʼλ�ã���ֱ�ӷ���
		if (inStr.length() < (columnSize - beginPos)){
			return inStr;
		}
		//����ÿ�п��
		int width = columnSize - beginPos - 2;
		
		if(inStr.startsWith("'")){
			sb.append(adjustStringIntern(beginPos, inStr.substring(1,inStr.length() -1),  width, "'"));
		}
		else if(inStr.startsWith("\"")){
			sb.append(adjustStringIntern(beginPos, inStr.substring(1,inStr.length() -1),  width, "\""));
		}
		else {
			sb.append(adjustStringIntern(beginPos, inStr,  width, "\""));
			
		}
		
		return sb.toString();
	}
	/**
	 * @param beginPos
	 * @param inStr
	 * @param sb
	 * @param width
	 * @param firstLine
	 */
	private static String adjustStringIntern(int beginPos, String inStr,
			 int width,String prefix) {
		StringBuffer sb = new StringBuffer();
		int subStrBeginPos = 0;
		int subStrEndPos = 0;
		boolean firstLine = true;
		while(subStrBeginPos < inStr.length()){
			String subString;
			
			int crlfindex = inStr.indexOf("\n", subStrBeginPos);
			
			if ((subStrBeginPos + width ) < inStr.length()){
				if ( (-1 != crlfindex) && (crlfindex < subStrBeginPos + width)){
					subStrEndPos = crlfindex + 1;
				}
				else {
					if (inStr.charAt(subStrBeginPos + width -1) == '\\'){
						//ת���ַ���Ҫ����һ���ַ�Ҳ���ڱ��У���������ת�����
						subStrEndPos = subStrBeginPos + width + 1;
					}
					else 
					{
						subStrEndPos = subStrBeginPos + width;
					}
					
				}
				
			}
			else {
				if ((-1 != crlfindex) && (crlfindex < inStr.length())){
					subStrEndPos = crlfindex + 1;
				}
				else {
					subStrEndPos = inStr.length();
				}
				
			}
			if (subStrBeginPos >= subStrEndPos){
				assert(false);
			}
			subString = inStr.substring(subStrBeginPos, subStrEndPos);

			
			if (firstLine){
				if (subStrEndPos == crlfindex + 1){
					sb.append(convert2DQValue(subString));
				}
				else {
					sb.append(prefix);
					sb.append(subString);
					sb.append(prefix);
				}
				
				firstLine = false;
			}
			else {
				String lineString = null;
				lineString = buildLinePrefix(beginPos - 2);
				lineString += "+ ";
				if (subStrEndPos == crlfindex + 1){
					lineString += convert2DQValue(subString);
				}
				else {
					lineString += prefix;
					lineString += subString;
					lineString += prefix;
				}
						
				sb.append(lineString);
			}
			if (subStrEndPos == inStr.length()){
				subStrBeginPos = inStr.length();
			}
			else {				
				subStrBeginPos = subStrEndPos;				
			}
			
			
		}
		return sb.toString();
	}
	public static String toYangString(YangStatement statement,YangFormatter format,String curIndentation){
		String yangStr = null;
		if (null == curIndentation){
			yangStr = new String(statement.getKeyword());
		}
		else{
			yangStr = new String(curIndentation);
			yangStr = yangStr.concat(statement.getKeyword());
		}
		yangStr += " ";
		if(statement.getKeyword().equals("typedef") 
				&& (statement.getArgument().equals("range"))){
			int i = 0;
			i++;
		}
		int argPos = yangStr.length();
		String argString;
		if(statement.isIsNeedQuotes()){
			argString= convert2QuotesValue(statement.getArgument());
		}
		else {
			argString= statement.getArgument();
		}
		String adjustArgString = adjustString(argPos, argString, format.getColumnSize());
		if (null == adjustArgString){
//			System.out.println("keyword:" +  statement.getKeyword() + " argument:"
//					+ statement.getArgument());
		}
		else {
			yangStr += adjustArgString;
			if (!adjustArgString.equals(argString)){
				yangStr += buildLinePrefix(argPos);
			}
			else {
				yangStr += " ";
			}
		}

		if (0 == statement.getChildrenNumber()){
			yangStr += ";";
		}
		else {
			yangStr += "{";
			yangStr += format.getEndWith();
			String nextIndentation;
			if (null == curIndentation){
				nextIndentation = format.getIndentation();
			}
			else
			{
				nextIndentation = curIndentation + format.getIndentation();
			}
			
			int size = statement.getChildrenNumber();
			for (int i=0; i<size;i++){
				YangStatement subStatement = statement.getChild(i);
				yangStr += toYangString(subStatement,format,nextIndentation);
			}
			if (null != curIndentation){
				yangStr += curIndentation;
			}
			
			yangStr += "}";
		}
		yangStr += format.getEndWith();
		
		return yangStr;
	}
}
